package main

import (
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/text/gstr"
	"os"
	"strings"
)

func startServerManager() {
	s2 := g.Server("manager")

	s2.Group("", func(group *ghttp.RouterGroup) {
		group.Middleware(func(r *ghttp.Request) {
			if r.URL.Path == "login" {
				r.Middleware.Next()
				return
			}
			u, _ := r.Session.Get("user", "")

			g.Log().Info(r.GetCtx(), u)
			if u.IsEmpty() {
				_ = r.Response.WriteTpl("proxy/login.html")
				return
			}
			r.Middleware.Next()
		})

		group.GET("/login", func(r *ghttp.Request) {
			err := r.Response.WriteTpl("proxy/login.html")
			if err != nil {
				return
			}
		})
		group.GET("/", IndexPage)
		group.GET("/index", IndexPage)
		group.GET("/add", func(r *ghttp.Request) {
			err := r.Response.WriteTpl("proxy/add.html")
			if err != nil {
				return
			}
		})
		group.GET("/edit", func(r *ghttp.Request) {
			id := r.GetQuery("id", -1).Int()
			data, err := g.Model("t_address").Where("id = ?", id).One()

			if err != nil {
				g.Log().Error(ctx, err)
				_ = r.Response.WriteTpl("proxy/404.html")
				return
			}
			var d = data.Map()
			if d == nil || d["id"] == nil || d["id"] == 0 {
				g.Log().Error(ctx, err)
				_ = r.Response.WriteTpl("proxy/404.html")
				return
			}
			_ = r.Response.WriteTpl("proxy/edit.html", d)
		})
	})
	s2.Group("/manager", func(group *ghttp.RouterGroup) {
		group.POST("/login", Login)
		group.POST("/logout", Logout)
	})
	s2.Group("/manager/api", func(group *ghttp.RouterGroup) {
		group.Middleware(func(r *ghttp.Request) {
			u, _ := r.Session.Get("user", "")
			if u == nil {
				g.Log().Error(ctx, "未登录")
				r.Response.WriteJson(g.Map{
					"code": -1, "msg": "请先登录",
				})
				return
			}
			r.Middleware.Next()
		})
		group.Group("/proxy", func(group *ghttp.RouterGroup) {
			group.ALL("/data", ProxyData)
			group.GET("/get", ProxyGet)
			group.ALL("/list", ProxyList)
			group.POST("/new", ProxyNew)
			group.POST("/edit", ProxyEdit)
			group.POST("/start", ProxyStart)
			group.POST("/stop", ProxyStop)
			group.POST("/delete", ProxyDelete)
		})
		group.POST("/ssl_renew", UpdateSSl)
	})
	//s2.BindHandler("/ssl_renew", UpdateSSl)
	s2.SetPort(g.Cfg().MustGet(ctx, "app.manager_port", 22979).Int())
	s2.SetIndexFolder(true)
	g.Log().Info(ctx, "服务器启动成功")
	s2.Run()
}

func IndexPage(r *ghttp.Request) {
	var doMain = gstr.TrimLeft(domain, "*")
	var scheme = "http"
	if isSSlAuto {
		scheme = "https"
	}
	err := r.Response.WriteTpl("proxy/index.html", map[string]interface{}{
		"proxyUrl": fmt.Sprintf("%s:%d", doMain, s.GetListenedPort()),
		"scheme":   scheme,
	})
	if err != nil {
		return
	}
}

func Logout(r *ghttp.Request) {
	_ = r.Session.Remove("user")
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
	})
}

func Login(r *ghttp.Request) {
	var param map[string]interface{}
	param = r.GetFormMap()
	g.Log().Print(r.GetCtx(), param)
	username, _ := param["username"].(string)
	password, _ := param["password"].(string)
	bs, err := os.ReadFile("config/user.json")
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJson(g.Map{
			"code": -1, "msg": "登录失败 " + err.Error(),
		})
		return
	}
	var m map[string]string
	err = json.Unmarshal(bs, &m)
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJson(g.Map{
			"code": -1, "msg": "登录失败 " + err.Error(),
		})
		return
	}
	g.Log().Info(r.GetCtx(), m)
	pwd, ok := m[username]
	if !ok {
		g.Log().Error(ctx, "登录失败，用户不存在")
		r.Response.WriteJson(g.Map{
			"code": -1, "msg": "登录失败，用户或密码不对",
		})
		return
	}
	if password != pwd {
		g.Log().Error(ctx, "登录失败 ，密码不对")
		r.Response.WriteJson(g.Map{
			"code": -1, "msg": "登录失败，用户或密码不对",
		})
		return
	}
	_ = r.Session.Set("user", "admin")
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
	})
}

func UpdateSSl(r *ghttp.Request) {
	err := ReNewSSLCert()
	if err != nil {
		return
	}
	r.Response.Writeln("更新完成")
}

type EditAddressReq struct {
	Id      uint   `v:"id   @integer|min:1#|请输入用户ID"`
	Name    string `p:"name"  v:"required#请输入前缀"`
	Address string `p:"address" v:"required#请输入转发地址"`
	Remark  string `p:"remark"`
	Enable  string
	Host    bool `p:"host"`
}

type IdReq struct {
	Id   uint   `v:"id   @integer|min:1#|请输入用户ID"`
	Name string `p:"name"  v:"required#请输入前缀"`
}

type NewAddressReq struct {
	Name    string `p:"name"  v:"required#请输入前缀"`
	Address string `p:"address" v:"required#请输入转发地址"`
	Remark  string `p:"remark"`
	Host    bool   `p:"host"`
}

func ProxyData(r *ghttp.Request) {
	r.Response.WriteJson(proxyStr)
}
func ProxyNew(r *ghttp.Request) {
	var data NewAddressReq
	err := r.ParseForm(&data)
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}

	m := g.Model("t_address")
	data.Name = strings.ToLower(data.Name)
	_, err = m.Insert(data)
	if err != nil {
		g.Log().Error(ctx, data, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
	})
}

func ProxyEdit(r *ghttp.Request) {
	var data EditAddressReq
	err := r.ParseForm(&data)
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	data.Enable = "N"
	m := g.Model("t_address")
	data.Name = strings.ToLower(data.Name)
	_, err = m.Data(data).Where("id = ?", data.Id).Update()
	if err != nil {
		g.Log().Error(ctx, data, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	delete(proxyStr, data.Name)
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
	})
}

func ProxyStart(r *ghttp.Request) {
	var data IdReq
	err := r.ParseForm(&data)
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}

	var address Address
	if err := g.Model("t_address").Where("id = ?", data.Id).Scan(&address); err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	g.Log().Print(ctx, address)
	_, err = g.Model("t_address").Data(g.Map{"enable": "Y"}).Where("id = ?", data.Id).Update()
	if err != nil {
		g.Log().Error(ctx, data, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	proxyStr[address.Name] = ProxyInfo{Address: address.Address, Host: address.Host}
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
	})
}

func ProxyStop(r *ghttp.Request) {
	var data IdReq
	err := r.ParseForm(&data)
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}

	var address Address
	if err := g.Model("t_address").Where("id = ?", data.Id).Scan(&address); err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	_, err = g.Model("t_address").Data(g.Map{"enable": "N"}).Where("id = ?", data.Id).Update()
	if err != nil {
		g.Log().Error(ctx, data, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	delete(proxyStr, address.Name)
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
	})
}

func ProxyDelete(r *ghttp.Request) {
	var data IdReq
	err := r.ParseForm(&data)
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}

	var address Address
	if err := g.Model("t_address").Where("id = ?", data.Id).Scan(&address); err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}

	_, err = g.Model("t_address").Delete(g.Map{"id": data.Id})
	if err != nil {
		g.Log().Error(ctx, data, err)
		r.Response.WriteJsonExit(g.Map{
			"code": -1, "msg": err.Error(),
		})
	}
	delete(proxyStr, address.Name)
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
	})
}

func ProxyGet(r *ghttp.Request) {
	id := r.GetQuery("id", -1).Int()
	data, err := g.Model("t_address").Where("id = ?", id).One()
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJson(g.Map{
			"code": -1, "msg": err.Error(),
		})
		return
	}
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
		"data": data,
	})
}

func ProxyList(r *ghttp.Request) {
	query := r.Get("query", "").String()
	whereMap := map[string]string{}
	if len(query) > 0 {
		err := json.Unmarshal([]byte(query), &whereMap)
		if err != nil {
			g.Log().Error(ctx, err)
			r.Response.WriteJson(g.Map{
				"code": -1, "msg": err.Error(),
			})
			return
		}
	}

	m := g.Model("t_address")
	for k1, v1 := range whereMap {
		if len(v1) > 0 {
			m.WhereLike(k1, fmt.Sprintf("%%%s%%", v1))
		}
	}
	total, err := m.Count()
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJson(g.Map{
			"code": -1, "msg": err.Error(),
		})
		return
	}
	data, err := m.Page(r.Get("page", 1).Int(), r.Get("limit", 20).Int()).All()
	if err != nil {
		g.Log().Error(ctx, err)
		r.Response.WriteJson(g.Map{
			"code": -1, "msg": err.Error(),
		})
		return
	}
	r.Response.WriteJson(g.Map{
		"code": 0, "msg": "ok",
		"data":  data,
		"count": total,
	})
}
